fix(tags): read Emby tags from TagItems — ToDelete state was wrong on the wall#51
Merged
Conversation
… the wall
Emby serves applied tags under `TagItems` ([{Name,Id}]) and returns the
legacy `Tags` string list as null on BOTH the item list and detail endpoints
(probed live on greg 2026-07-15). Three sites read `item["Tags"]` directly:
- cell.py:629 — the red ToDelete button computed `checked=False` for an
already-tagged clip loaded from the library (confirmed: the two files just
tagged came back Tags=None / TagItems=[ToDelete] via the exact fetch_items
query, so the indicator lied).
- cell.py _toggle_tag — read `item["Tags"]` to decide add-vs-remove;
`setdefault("Tags", [])` returns the null, so `list(None)` would raise on a
library-loaded tagged clip (and mis-toggle even if it didn't).
- wall.py update_tags — built the POST body from `Tags`, so it could drop a
tag it never saw.
Fix: one pure helper `urls.tag_names(item)` that prefers TagItems and falls
back to Tags (string list or dict list), used at all three sites. `_toggle_tag`
now keeps both shapes in sync in the local dict so the helper reflects the new
state on the next read. The WRITE path is unchanged — Emby rebuilds TagItems
from the posted `Tags` string list (verified: the manual tag persisted).
Tests: 6 in test_urls.py covering the real Emby shape (Tags=null +
TagItems), precedence, both fallbacks, empty/missing safety, and the
untagged-vs-tagged checked computation. Suite green at v10.13.2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Emby serves applied tags under
TagItems([{Name, Id}]) and returns the legacyTagsstring list asnull— on both the item list and detail endpoints. Probed live on greg (2026-07-15): the two files just taggedToDeletecome back asTags: None,TagItems: [{Name: "ToDelete", Id: 21516}]via the exact queryfetch_itemsuses.Three sites read
item["Tags"]directly and all get it wrong:checked=Falsefor an already-tagged clip loaded from the library. The indicator lies: tagged clips look untagged.cell.py_toggle_tag— readsitem["Tags"]to decide add-vs-remove;setdefault("Tags", [])returns thenull, solist(None)raises on a library-loaded tagged clip (and mis-toggles even where it doesn't crash).wall.pyupdate_tags— builds the POST body fromTags, so it can silently drop a tag it never saw.Fix
One pure helper
urls.tag_names(item)that prefersTagItems, falling back toTags(string list or dict list), used at all three sites._toggle_tagnow keeps both shapes in sync in the local dict so the helper reflects the new state on the next read.The write path is unchanged — Emby rebuilds
TagItemsfrom the POSTedTagsstring list (verified: the manual tag applied earlier today persisted and shows up in the cleanup pipeline'sTags=ToDeletequery).Tests
6 new in
test_urls.py(pure, no Qt/Emby): the real Emby shape (Tags=null+TagItems),TagItemsprecedence, both fallbacks, empty/missing safety, and the untagged-vs-taggedcheckedcomputation that reproduces the user-visible symptom. Suite green at v10.13.2.Context
Found while tagging two soak-identified problem files for deletion — the "did it persist?" check initially read the wrong field, which surfaced this latent bug. Tagging itself works end-to-end; this is purely the read-back/display side.
Verify
Deterministic + unit-tested, so no soak needed. Rebuild (
build.ps1, pwsh 7) and confirm the logRuntime:banner reads v10.13.2; the red tag glyph should now light for already-tagged clips on load.🤖 Generated with Claude Code